<template>
  <div class="image-uploader">
    <el-upload
      :action="uploadUrl"
      :headers="headers"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-exceed="handleExceed"
      :before-upload="beforeUpload"
      :data="uploadData"
      :limit="limit"
      :multiple="multiple"
      :list-type="listType"
      :file-list="fileList"
      :disabled="disabled"
      :class="{ 'image-uploader-grid': listType === 'picture-card' }"
    >
      <template #default>
        <div v-if="listType === 'picture-card'" class="image-uploader-trigger">
          <el-icon><Plus /></el-icon>
          <span>{{ buttonText || "点击上传" }}</span>
        </div>
        <el-button v-else type="primary" :disabled="disabled">
          {{ buttonText || "点击上传" }}
        </el-button>
      </template>
      <template #file="{ file }">
        <div v-if="listType === 'picture-card'" class="image-uploader-item">
          <img :src="file.url" class="image-uploader-img" />
          <div class="image-uploader-actions">
            <el-button type="primary" link @click.stop="handlePreview(file)">
              <el-icon><ZoomIn /></el-icon>
            </el-button>
            <el-button type="danger" link @click.stop="handleRemove(file)">
              <el-icon><Delete /></el-icon>
            </el-button>
          </div>
        </div>
      </template>
    </el-upload>

    <!-- 图片预览对话框 -->
    <el-dialog v-model="previewVisible" title="图片预览" width="50%">
      <img :src="previewUrl" style="width: 100%" />
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, watch } from "vue";
import { ElMessage } from "element-plus";
import { Plus, ZoomIn, Delete } from "@element-plus/icons-vue";
import request from "@/utils/request";

const props = defineProps({
  // 上传URL，默认为/api/image/upload
  action: {
    type: String,
    default: "/api/image/upload",
  },
  // 图片类型
  type: {
    type: String,
    default: "",
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false,
  },
  // 上传按钮文本
  buttonText: {
    type: String,
    default: "",
  },
  // 上传数量限制
  limit: {
    type: Number,
    default: 5,
  },
  // 是否允许多选
  multiple: {
    type: Boolean,
    default: true,
  },
  // 列表展示方式：text/picture/picture-card
  listType: {
    type: String,
    default: "picture-card",
  },
  // v-model绑定的值（图片URL数组或单个URL字符串）
  modelValue: {
    type: [String, Array],
    default: () => [],
  },
});

const emit = defineEmits([
  "update:modelValue",
  "upload-success",
  "upload-error",
  "remove",
]);

// 上传地址
const uploadUrl = computed(() => props.action);

// 上传时附带的数据
const uploadData = computed(() => {
  const data = {};
  if (props.type) {
    data.type = props.type;
  }
  return data;
});

// 请求头信息，可根据实际情况设置认证信息
const headers = computed(() => {
  return {};
});

// 文件列表
const fileList = ref([]);

// 预览相关
const previewVisible = ref(false);
const previewUrl = ref("");

// 监听modelValue变化，同步到fileList
watch(
  () => props.modelValue,
  (newVal) => {
    // 如果是数组类型
    if (Array.isArray(newVal)) {
      fileList.value = newVal
        .map((url, index) => {
          if (typeof url === "string") {
            return { name: `图片${index + 1}`, url };
          } else if (typeof url === "object" && url.url) {
            return { name: url.name || `图片${index + 1}`, url: url.url };
          }
          return null;
        })
        .filter((item) => item !== null);
    }
    // 如果是字符串类型（单张图片）
    else if (typeof newVal === "string" && newVal) {
      fileList.value = [{ name: "图片", url: newVal }];
    }
    // 空值
    else {
      fileList.value = [];
    }
  },
  { immediate: true, deep: true }
);

// 上传前的处理
const beforeUpload = (file) => {
  // 检查文件类型
  const isImage = file.type.startsWith("image/");
  if (!isImage) {
    ElMessage.error("只能上传图片文件!");
    return false;
  }

  // 检查文件大小 (10MB)
  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isLt10M) {
    ElMessage.error("图片大小不能超过10MB!");
    return false;
  }

  return true;
};

// 上传成功的处理
const handleSuccess = (response, file, fileList) => {
  if (response.code === 200 && response.data) {
    // 获取上传后的图片信息
    const image = response.data;

    // 更新v-model值
    updateModelValue(fileList);

    // 触发上传成功事件
    emit("upload-success", image, file, fileList);

    ElMessage.success("上传成功");
  } else {
    handleError(response, file, fileList);
  }
};

// 上传失败的处理
const handleError = (error, file, fileList) => {
  let message = "上传失败";
  if (error && error.message) {
    message = error.message;
  } else if (error && error.data && error.data.message) {
    message = error.data.message;
  }

  emit("upload-error", error, file, fileList);
  ElMessage.error(message);
};

// 超出上传限制
const handleExceed = (files, fileList) => {
  ElMessage.warning(`最多只能上传${props.limit}张图片`);
};

// 预览图片
const handlePreview = (file) => {
  previewUrl.value = file.url;
  previewVisible.value = true;
};

// 删除图片
const handleRemove = async (file) => {
  // 如果文件有id属性，说明已经上传到服务器，尝试删除
  if (file.id) {
    try {
      const res = await request({
        url: `/api/image/${file.id}`,
        method: "delete",
      });

      if (res.code === 200) {
        ElMessage.success("删除成功");
      } else {
        ElMessage.error("删除失败");
      }
    } catch (error) {
      console.error("删除图片失败", error);
      ElMessage.error("删除失败");
    }
  }

  // 从文件列表中移除
  fileList.value = fileList.value.filter((item) => item.url !== file.url);

  // 更新v-model值
  updateModelValue(fileList.value);

  // 触发删除事件
  emit("remove", file);
};

// 更新v-model值
const updateModelValue = (files) => {
  if (Array.isArray(props.modelValue)) {
    // 返回URL数组
    const urls = files.map((file) => file.url || file.response?.data?.url);
    emit("update:modelValue", urls);
  } else {
    // 返回单个URL（取最后上传的）
    const lastFile = files[files.length - 1];
    const url = lastFile ? lastFile.url || lastFile.response?.data?.url : "";
    emit("update:modelValue", url);
  }
};
</script>

<style scoped>
.image-uploader {
  width: 100%;
}

.image-uploader-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.image-uploader-trigger {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: #8c939d;
  font-size: 14px;
}

.image-uploader-item {
  position: relative;
  overflow: hidden;
  border-radius: 4px;
}

.image-uploader-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-uploader-actions {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity 0.3s;
}

.image-uploader-item:hover .image-uploader-actions {
  opacity: 1;
}
</style>
